package service

import (
	"leaf/core/event"
	"leaf/core/log"
	"leaf/core/rpc"
	"leaf/core/service/timer"
	"leaf/core/tool"
	"time"
)

const (
	TimerDispatcherLen = 100
)

type IServiceInit interface {
	OnInit()
}

type ITimer interface {
	Timer()
}

type Service struct {
	serviceName string
	threadNum   int32
	OnStart     func()
	serviceRpc  *rpc.ServicRpc
	dispatcher  *timer.Dispatcher
	eventChanel *event.EventChannel
	timers      []*timer.Timer
}

func NewService(threadNum int32) *Service {
	s := new(Service)
	s.serviceRpc = new(rpc.ServicRpc)
	s.dispatcher = timer.NewDispatcher(TimerDispatcherLen)
	s.eventChanel = new(event.EventChannel)
	s.threadNum = threadNum
	return s
}

//func (s *Service) GetServiceType() string {
//	return reflect.TypeOf(s).Name()
//}
//
//func (s *Service) GetServiceName() string {
//	return s.serviceName
//}

//func (s *Service) SetServiceName(serviceName string) {
//	s.serviceName = serviceName
//}

func (s *Service) SetServiceThreadNum(threadNum int32) {
	s.threadNum = threadNum
}

func (s *Service) Init(serv interface{}) {
	s.serviceRpc.Init(serv)
	s.eventChanel.Init(serv)
	if s.threadNum == 0 {
		s.threadNum = 1
	}
	if iface, ok := serv.(IServiceInit); ok {
		iface.OnInit()
	}
	if iface, ok := serv.(ITimer); ok {
		if t := s.NewTimer(time.Second, func() { iface.Timer() }); t != nil {
			s.timers = append(s.timers, t)
		}
	}
}

func (s *Service) Destroy() {
	log.Debug("service destroy")
	s.serviceRpc.OnClose()
}

func (this *Service) Run(closeSig chan bool) {
	if this.OnStart != nil {
		this.OnStart()
	}
	for {
		select {
		case <-tool.GoSigChan():
			log.Release("service close sig")
			return
		case c := <-this.serviceRpc.GetChannel():
			this.serviceRpc.Cb(c)
		case e := <-this.eventChanel.GetChannel():
			this.eventChanel.GetEventHandler().EventHandler(e)
		case t := <-this.dispatcher.ChanTimer:
			t.Cb()
		}
	}
}

func (s *Service) GetThreadNum() int32 {
	return s.threadNum
}

func (s *Service) GetServiceRpc() *rpc.ServicRpc {
	return s.serviceRpc
}

func (s *Service) GetEventChannel() *event.EventChannel {
	return s.eventChanel
}

func (s *Service) GetServicRpc() *rpc.ServicRpc {
	return s.serviceRpc
}

func (s *Service) EventHandler(e event.IEvent) {

}

func (s *Service) NewTimer(d time.Duration, cb func()) *timer.Timer {
	return s.dispatcher.AfterFunc(d, cb)
}

func (s *Service) AfterFunc(d time.Duration, cb func(), ct ...int32) *timer.Timer {
	return s.dispatcher.AfterFunc(d, cb, ct...)
}

func (s *Service) CronFunc(cronExpr *timer.CronExpr, cb func()) *timer.Cron {
	return s.dispatcher.CronFunc(cronExpr, cb)
}
